package com.mzj.saas.commons.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;

/**
 * @Description
 * @Author ???
 * @Date 2018年1月10日下午4:51:39
 * @Version 1.0
 */
public class DateUtils {

	private static final Logger LOG = LoggerFactory.getLogger(DateUtils.class);

	/**
	 * yyyyMMddHHmmss
	 */
	public static final String FORMAT_14 = "yyyyMMddHHmmss";

	/**
	 * yyyyMMddhhmm
	 */
	public static final String FORMAT_12 = "yyyyMMddhhmm";
	/**
	 * yyyy-MM
	 */
	public static final String FORMAT_13 = "yyyy-MM";


	/**
	 * yyyy-MM-dd HH:mm:ss
	 */
	public static final String FORMAT_DATETIME_14 = "yyyy-MM-dd HH:mm:ss";

	/**
	 * yyyy-MM-dd HH:mm:ss.SSS
	 */
	public static final String FORMAT_DATETIME_HM_14 = "yyyy-MM-dd HH:mm:ss.SSS";

	public static final String FORMAT_DATATIME_DATE = "yyyy-MM-dd'T'hh:mm:ss.SSSZ";

	/**
	 * yyyy-MM-dd HH:mm:ss.SSS
	 */
	public static final String FORMAT_HM_14 = "yyyyMMddHHmmssSSS";

	/**
	 * yyyyMM
	 */
	public static final String FORMAT_6 = "yyyyMM";

	/**
	 * MMdd
	 */
	public static final String FORMAT_7 = "yyMM";

	/**
	 * yyyyMMdd
	 */
	public static final String FORMAT_8 = "yyyyMMdd";

	/**
	 * yyyy-MM-dd
	 */
	public static final String FORMAT_DATE_8 = "yyyy-MM-dd";

	/**
	 * yyyy-MM-dd HH:mm
	 */
	public static final String FORMAT_DATETIME_15 = "yyyy-MM-dd HH:mm";

	private DateUtils() {

	}

	public static String format(String time, String rformat, String sformat) {
		SimpleDateFormat fmt = new SimpleDateFormat(rformat);
		Date ndate = null;
		try {
			ndate = fmt.parse(time);
			SimpleDateFormat format = new SimpleDateFormat(sformat);
			return format.format(ndate);
		} catch (ParseException e) {
			LOG.error(e.getMessage(), e);
			return null;
		}
	}

	public static String format(Date date, String format) {
		SimpleDateFormat sformat = new SimpleDateFormat(format);
		return sformat.format(date);
	}

	public static Date convert(String time, String format) {
		SimpleDateFormat sformat = new SimpleDateFormat(format);
		try {
			return sformat.parse(time);
		} catch (ParseException e) {
			LOG.error(e.getMessage(), e);
		}
		return null;
	}

	public static String datetimeToString(Date date, String format) {
		Date dateTime = date;
		if (dateTime == null) {
			dateTime = new Date();
		}
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		return sdf.format(dateTime);
	}

	public static Date stringToDateTime(String str, String format) throws ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		return sdf.parse(str);
	}

	public static String datetimeToStringForTags(Date date, String format) {
		if (date == null) {
			return "";
		}
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		return sdf.format(date);
	}

	public static Date stringToDateTimeForTags(String str, String format) {
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		try {
			return sdf.parse(str);
		} catch (ParseException e) {
			return null;
		}
	}

	/**
	 * when date1 earlier than date2 ,return -1 when date1 equals date2 ,return 0
	 * when date1 later than date2 ,return 1
	 *
	 * @param date1
	 * @param date2
	 * @return
	 * @throws ParseException
	 * @throws
	 */
	public static int compareDate(String date1, String date2, String dateFormat) throws ParseException {

		DateFormat df = new SimpleDateFormat(dateFormat);

		try {
			Date dt1 = df.parse(date1);
			Date dt2;
			dt2 = df.parse(date2);

			if (dt1.getTime() > dt2.getTime()) {
				return 1;
			} else if (dt1.getTime() < dt2.getTime()) {
				return -1;
			} else {
				return 0;
			}
		} catch (ParseException e) {
			throw e;

		}
	}

	/**
	 * 计算2个日期相差多少天
	 *
	 * @param smdate
	 * @param bdate
	 * @return
	 * @throws ParseException
	 */
	public static int daysBetween(Date smdate, Date bdate) throws ParseException {

		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		smdate = sdf.parse(sdf.format(smdate));
		bdate = sdf.parse(sdf.format(bdate));

		Calendar cal = Calendar.getInstance();

		cal.setTime(smdate);
		long time1 = cal.getTimeInMillis();

		cal.setTime(bdate);
		long time2 = cal.getTimeInMillis();

		long between_days = (time2 - time1) / (1000 * 3600 * 24);
		return Integer.parseInt(String.valueOf(between_days));

	}

	/**
	 * 计算2个日期相差多少小时
	 *
	 * @param smdate
	 * @param bdate
	 * @return
	 * @throws ParseException
	 */
	public static int hoursBetween(Date smdate, Date bdate) throws ParseException {

		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHH");
		smdate = sdf.parse(sdf.format(smdate));
		bdate = sdf.parse(sdf.format(bdate));

		Calendar cal = Calendar.getInstance();
		cal.setTime(smdate);

		long time1 = cal.getTimeInMillis();
		cal.setTime(bdate);

		long time2 = cal.getTimeInMillis();

		long between_hours = (time2 - time1) / (1000 * 3600);
		return Integer.parseInt(String.valueOf(between_hours));

	}

	/**
	 * 得到指定日期，几天前或几天后的日期
	 *
	 * @param date
	 * @param format
	 * @param days
	 * @return
	 */
	public static String getAddDaysTime(String date, String format, int days) {
		Calendar cal = Calendar.getInstance();
		Date fDate = stringToDateTimeForTags(date, format);
		cal.setTime(fDate);
		cal.add(Calendar.DAY_OF_MONTH, days);
		return new SimpleDateFormat(format).format(cal.getTime());
	}

	public static String getAddDaysTime(Date date, String format, int days) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(5, days);
		return (new SimpleDateFormat(format)).format(cal.getTime());
	}

	public static Date getAddDaysTime(Date date, int days) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(5, days);
		return cal.getTime();
	}
	/**
	 * 计算参数日期与当前时间相差天数
	 *
	 * @param createTime
	 * @return
	 * @author shun
	 * @date 2020年10月29日
	 */
	public static Integer getDataDifferenceDay(String createTime) {
		LocalDate endDate = LocalDate.now();
		DateTimeFormatter fmt = DateTimeFormatter.ofPattern(FORMAT_DATETIME_14);
		LocalDate startDate = LocalDate.parse(createTime, fmt);

		Period period = Period.between(startDate, endDate);
		return period.getDays();
	}

	/**
	 * 得到指定日期，几分钟前或几分钟后的日期
	 *
	 * @param date
	 * @param format
	 * @param minutes
	 * @return
	 */
	public static String getAddMinutesTime(String date, String format, int minutes) {
		Calendar cal = Calendar.getInstance();
		Date fDate = stringToDateTimeForTags(date, format);
		cal.setTime(fDate);
		cal.add(Calendar.MINUTE, minutes);
		return new SimpleDateFormat(format).format(cal.getTime());
	}

	public static String getAddMinutesTime(Date date, String format, int minutes) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.MINUTE, minutes);
		return (new SimpleDateFormat(format)).format(cal.getTime());
	}

	public static Date getAddMinutesTime(Date date, int minutes) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.MINUTE, minutes);
		return cal.getTime();
	}

	/**
	 * 得到指定日期 几天后
	 *
	 * @param date
	 * @param minutes
	 * @return
	 */
	public static String getAddYEARTime(Date date, String format, int minutes) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.DAY_OF_YEAR, minutes);
		return (new SimpleDateFormat(format)).format(cal.getTime());
	}

	/**
	 * 获取当前系统下一天日期
	 *
	 * @param date
	 * @return
	 */
	public static Date getTomorrow(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DAY_OF_MONTH, +1);
		date = calendar.getTime();
		return date;
	}

	/**
	 * 获取当前系统前一天日期
	 *
	 * @param date
	 * @return
	 */
	public static Date getYesterday(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DAY_OF_MONTH, -1);
		date = calendar.getTime();
		return date;
	}

	/**
	 * 获取当前系统时间前一天最大时间
	 * @return
	 */
	public static Date getYesterdayMaxTime(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DAY_OF_MONTH, -1);
		calendar.set(Calendar.HOUR_OF_DAY,23);
		calendar.set(Calendar.MINUTE,59);
		calendar.set(Calendar.SECOND,59);
		//防止mysql自动加一秒,毫秒设为0
		calendar.set(Calendar.MILLISECOND, 0);
		date = calendar.getTime();
		return date;
	}




	/**
	 * 根据年 月 获取对应的月份 天数
	 */
	public static int getDaysByYearMonth(int year, int month) {

		Calendar a = Calendar.getInstance();
		a.set(Calendar.YEAR, year);
		a.set(Calendar.MONTH, month - 1);
		a.set(Calendar.DATE, 1);
		a.roll(Calendar.DATE, -1);
		int maxDate = a.get(Calendar.DATE);
		return maxDate;
	}

	public static int differentDays(Date date1, Date date2) {
		try {
			Calendar cal1 = Calendar.getInstance();
			cal1.setTime(date1);

			Calendar cal2 = Calendar.getInstance();
			cal2.setTime(date2);
			int day1 = cal1.get(Calendar.DAY_OF_YEAR);
			int day2 = cal2.get(Calendar.DAY_OF_YEAR);

			int year1 = cal1.get(Calendar.YEAR);
			int year2 = cal2.get(Calendar.YEAR);
			if (year1 != year2) { // 同一年
				int timeDistance = 0;
				for (int i = year1; i < year2; i++) {
					if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) {// 闰年
						timeDistance += 366;
					} else {// 不是闰年
						timeDistance += 365;
					}
				}

				return (timeDistance + (day2 - day1));
			} else {// 不同年
				// System.out.println("判断day2 - day1 : " + (day2 - day1));
				return (day2 - day1);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return 0;
	}

	/**
	 * 判断时间段内
	 *
	 * @param date
	 * @param startTime 00:00
	 * @param endTime   00:00
	 * @return
	 */
	@SuppressWarnings("deprecation")
	public static boolean timeHandle(Date date, String startTime, String endTime) {
		int hour = date.getHours();
		int minute = date.getMinutes();

		String minu = String.valueOf(hour > 9 ? hour : String.valueOf(0) + String.valueOf(hour))
				+ String.valueOf(minute > 9 ? minute : String.valueOf(0) + String.valueOf(minute));
		startTime = startTime.replaceAll(":", "");
		endTime = endTime.replaceAll(":", "");
		if (Long.parseLong(minu) >= Long.parseLong(startTime) && Long.parseLong(minu) <= Long.parseLong(endTime)) {
			return true;
		}

		return false;
	}

	/**
	 * 判断时间段相差
	 *
	 * @param startDate
	 * @param endDate
	 * @return
	 */
	public static int getMinutesDiff(String startDate, String endDate) {
		int ret = 0;

		String startDateStr[] = startDate.split(":");
		String endDateStr[] = endDate.split(":");
		if (startDateStr[0].startsWith("0")) {
			startDateStr[0] = startDateStr[0].substring(1);
		}
		if (startDateStr[1].startsWith("0")) {
			startDateStr[1] = startDateStr[1].substring(1);
		}
		if (endDateStr[0].startsWith("0")) {
			endDateStr[0] = endDateStr[0].substring(1);
		}
		if (endDateStr[1].startsWith("0")) {
			endDateStr[1] = endDateStr[1].substring(1);
		}
		int s = Integer.parseInt(startDateStr[0]) * 60 + Integer.parseInt(startDateStr[1]);
		int e = Integer.parseInt(endDateStr[0]) * 60 + Integer.parseInt(endDateStr[1]);
		ret = e - s;
		return ret;
	}

	/**
	 * 判断当天时是每月的第一天
	 *
	 * @return true是 false否
	 */
	public static boolean dayOne() {
		Calendar c = Calendar.getInstance();
		int date = c.get(Calendar.DATE);
		if (date == 1)
			return true;
		else
			return false;
	}

	/**
	 * 当前时间到凌晨0:00之间秒
	 *
	 * @return
	 */
	public static Long getTimeMillis() {
		long current = System.currentTimeMillis();// 当前时间毫秒数
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.DAY_OF_MONTH, 1);
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		long tomorrowzero = calendar.getTimeInMillis();
		long tomorrowzeroSeconds = (tomorrowzero - current) / 1000;
		return tomorrowzeroSeconds;
	}

	/**
	 * 获取时间前几天的时间
	 *
	 * @param referenceDate
	 * @param day
	 * @return
	 */
	public static Date getPreDay(Date referenceDate, int day) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(referenceDate);
		calendar.add(Calendar.DATE, -day);
		return calendar.getTime();
	}

	/**
	 * 获取时间秒数
	 *
	 * @param date
	 * @return
	 * @throws ParseException
	 */
	public static String getTimeInMillis(Date date) throws ParseException {

		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		long time = cal.getTimeInMillis();

		return String.valueOf(time);
	}


	/**
	 * 获取最小日期
	 *
	 * @param date
	 * @return
	 */
	public static Date getMintDay(Date date) {
		LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());

		// 通过LocalDateTime的 with方法设置某天的最小值和最大值！！
		LocalDateTime minDateTime = localDateTime.with(LocalTime.MIN);
		// 格式化日期
		Date fromDate = Date.from(minDateTime.atZone(ZoneId.systemDefault()).toInstant());

		return fromDate;
	}

	/**
	 * 获取最大日期
	 *
	 * @param date
	 * @return
	 */
	public static Date getMaxDay(Date date) {
		LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
		LocalDateTime maxDateTime = localDateTime.with(LocalTime.MAX);
		return Date.from(maxDateTime.atZone(ZoneId.systemDefault()).toInstant());
	}

	/**
	 * 获取指定月份的最大时间
	 *
	 * @return
	 */

	public static String getLastDayOfMonth1(Date date) throws ParseException {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		//设置年份
		//cal.set(Calendar.YEAR, date.getYear());
		//设置月份
		//cal.set(Calendar.MONTH, date.getMonth() - 1);
		//获取某月最大天数
		int lastDay = cal.getActualMaximum(Calendar.DATE);
		//设置日历中月份的最大天数
		cal.set(Calendar.DAY_OF_MONTH, lastDay);
		//格式化日期
		SimpleDateFormat sdf = new SimpleDateFormat(DateUtils.FORMAT_DATETIME_14);
		Date maxDay = getMaxDay(sdf.parse(sdf.format(cal.getTime())));
		return DateUtils.format(maxDay, DateUtils.FORMAT_DATETIME_14);
	}

	/**
	 * 获取指定月份的最小时间
	 *
	 * @param
	 * @param
	 * @return
	 */
	public static String getFirstDayOfMonth1(Date date) throws ParseException {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		//设置年份
		//cal.set(Calendar.YEAR, cal.get(Calendar.YEAR));
		//设置月份
		//cal.set(Calendar.MONTH,cal.get(Calendar.MONTH) - 1);
		//获取某月最小天数
		int firstDay = cal.getMinimum(Calendar.DATE);
		//设置日历中月份的最小天数
		cal.set(Calendar.DAY_OF_MONTH, firstDay);
		//格式化日期
		SimpleDateFormat sdf = new SimpleDateFormat(DateUtils.FORMAT_DATETIME_14);

		Date mintDay = getMintDay(sdf.parse(sdf.format(cal.getTime())));

		return DateUtils.format(mintDay, DateUtils.FORMAT_DATETIME_14);
	}

	/**
	 * pass
	 * 返回当前季度的开始时间
	 * @return Date
	 */
	public static Date getCurrentQuarterDateBegin(Date date){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int month = calendar.get(Calendar.MONTH);
		int quarter = month / 3 + 1;
		int startMonth = 1;
		if (quarter == 2){
			startMonth = 4;
		}else if(quarter == 3){
			startMonth = 7;
		}else if(quarter == 4){
			startMonth = 10;
		}
		calendar.set(Calendar.MONTH,startMonth - 1);
		calendar.set(Calendar.DAY_OF_MONTH,1);
		calendar.set(Calendar.HOUR_OF_DAY,0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND,0);
		return calendar.getTime();
	}

	/**
	 * 获取传入日期所在年的第一天
	 * @param date
	 * @return
	 */
	public static Date getFirstDayDateOfYear(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int last = cal.getActualMinimum(Calendar.DAY_OF_YEAR);
		cal.set(Calendar.DAY_OF_YEAR, last);
		return cal.getTime();
	}

	/**
	 * 除以100，保留2位
	 * @param value
	 * @return
	 */
	public static BigDecimal IntegerToBigdecimal(Integer value) {
		if(value == null) {
			return new BigDecimal(0.00).setScale(2, BigDecimal.ROUND_HALF_UP);
		}
		return new BigDecimal(Double.valueOf(value) / 100).setScale(2, BigDecimal.ROUND_HALF_UP);
	}

	/**
	 * 乘以100
	 * @param value
	 * @return
	 */
	public static Integer doubleToInteger(Double value) {

		if(value == null) {
			return 0;
		}

		BigDecimal a1 = BigDecimal.valueOf(value);
		BigDecimal b1 = BigDecimal.valueOf(100);
		BigDecimal result = a1.multiply(b1);// 相乘结果
		return result.intValue();
	}


	// 清除毫秒值
	public static Date getPreciseTime(Date date) {
		// 日历对象
		Calendar c = Calendar.getInstance();
		// 设置时间
		c.setTime(date);
		// 设置毫秒值为0
		c.set(Calendar.MILLISECOND, 0);

		return c.getTime();
	}



}
